<!DOCTYPE html>
<html>
  <head>
    <!-- 渲染属性 -->
    <!-- <script src="node_modules/three/build/three.js"></script> -->
    <script type="importmap">
      {
        "imports": {
          "three": "./node_modules/three/build/three.module.js",
          "three/addons/": "./node_modules/three/examples/jsm/"
        }
      }
    </script>
    <script type="module">
      import * as THREE from "three";
      // 浏览器控制台测试，是否引入成功
      console.log(THREE.Scene);
      console.log("完成");

      // 性能监视器
      import Stats from "three/addons/libs/stats.module.js";
      const stats = new Stats();
      stats.setMode(1);

      document.getElementById("monitor").appendChild(stats.domElement);

      // 场景
      var scene = new THREE.Scene();
      /*
      //环境光:没有特定方向，整体改变场景的光照明暗
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);
*/
      // 平行光
      /*
      const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
      // 设置光源的方向：通过光源position属性和目标指向对象的position属性计算
      directionalLight.position.set(80, 100, 50);
      // 方向光指向对象网格模型mesh，可以不设置，默认的位置是0,0,0
      //directionalLight.target = mesh;
      scene.add(directionalLight);
      */
      // 点光源
      const pointLight = new THREE.PointLight(0xffffff, 1.0);
      scene.add(pointLight);

      pointLight.position.set(0, 0, 60);

      // 引入dat.gui.js的一个类GUI
      import { GUI } from "three/addons/libs/lil-gui.module.min.js";

      // 实例化一个gui对象
      const gui = new GUI();

      // 光照强度属性.intensity
      console.log("pointLight.intensity", pointLight.intensity);
      // 通过GUI改变 pointLight 对象的 intensity 属性, 用鼠标拖动就行
      gui.add(pointLight, "intensity", 0, 2.0);

      // 摄像机
      var camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        2,
        1000
      );

      // 渲染器
      var renderer = new THREE.WebGLRenderer({
        antialias: true, // 抗锯齿
      });
      // 设置渲染背景
      renderer.setClearColor(0xcccccc);

      // 渲染器大小
      renderer.setSize(window.innerWidth, window.innerHeight);

      // 不同硬件设备的屏幕的设备像素比window.devicePixelRatio值可能不同
      console.log("查看当前屏幕设备像素比", window.devicePixelRatio);

      // 获取你屏幕对应的设备像素比.devicePixelRatio告诉threejs,以免渲染模糊问题
      // 小了就不清楚了
      renderer.setPixelRatio(window.devicePixelRatio);

      renderer.setClearColor(0x444444, 1); //设置背景颜色

      // 将渲染结果放到页面中
      document.body.appendChild(renderer.domElement);

      // 画一个盒子形状
      var geometry = new THREE.BoxGeometry(2, 2, 2);
      // 设置颜色
      var material = new THREE.MeshBasicMaterial({ color: 0xff0cc0 });

      // 创建这个盒子
      var cube = new THREE.Mesh(geometry, material);

      // 把盒子放到场景中
      scene.add(cube);

      // 摄像机位置
      camera.position.z = 50;

      // 随机创建大量的模型,测试渲染性能
      const num = 6; //控制长方体模型数量
      const meshArr = [];
      for (let i = 0; i < num; i++) {
        // const geometry = new THREE.BoxGeometry(5, 5, 5);

        //BoxGeometry：长方体
        let geometry;

        // 漫反射材料，没有光源，就是黑的
        let material;

        switch (i) {
          case 0:
            geometry = new THREE.BoxGeometry(10, 10, 10);
            // 高光材料，没有光源，就是黑的
            material = new THREE.MeshPhongMaterial({
              color: 0xfefcc0,
              side: THREE.DoubleSide, //两面可见
              shininess: 60,
            });
            break;
          case 1:
            // SphereGeometry：球体
            geometry = new THREE.SphereGeometry(5);
            // 漫反射材料，没有光源，就是黑的
            material = new THREE.MeshPhongMaterial({
              color: 0xfefcc0,
              side: THREE.DoubleSide, //两面可见
            });
            break;
          case 5:
            // SphereGeometry：球体
            geometry = new THREE.SphereGeometry(5);
            // 漫反射材料，没有光源，就是黑的
            material = new THREE.MeshLambertMaterial({
              color: 0xfefcc0,
              side: THREE.DoubleSide, //两面可见
            });
            break;
          case 2:
            // CylinderGeometry：圆柱
            geometry = new THREE.CylinderGeometry(5, 5, 10);
            // 漫反射材料，没有光源，就是黑的
            material = new THREE.MeshStandardMaterial({
              color: 0xff0cc0,
              side: THREE.DoubleSide, //两面可见
            });
            break;
          case 3:
            // PlaneGeometry：矩形平面
            geometry = new THREE.PlaneGeometry(10, 5);
            // 漫反射材料，没有光源，就是黑的
            material = new THREE.MeshPhysicalMaterial({
              color: 0xff0cc0,
              side: THREE.DoubleSide, //两面可见
            });
            break;
          case 4:
            // CircleGeometry：圆形平面
            geometry = new THREE.CircleGeometry(5);
            // 漫反射材料，没有光源，就是黑的
            material = new THREE.MeshBasicMaterial({
              color: 0xff0cc0,
              side: THREE.DoubleSide, //两面可见
            });
            break;
          default:
            break;
        }

        const mesh = new THREE.Mesh(geometry, material);
        meshArr.push(mesh);
        // 随机生成长方体xyz坐标
        const x = (Math.random() - 0.5) * 50;
        const y = (Math.random() - 0.5) * 50;
        const z = (Math.random() - 0.5) * 50;
        mesh.position.set(x, y, z);
        scene.add(mesh); // 模型对象插入场景中
      }

      // 渲染方法
      function render() {
        // 设置立方本的坐标变化
        // rotation 这个是旋转，单位是弧度，一圈是 2PI
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        cube.rotation.z += 0.01;

        //camera.position.z -= 1;

        meshArr.forEach((m) => {
          m.rotation.x += Math.random() * 0.01;
          m.rotation.y += Math.random() * 0.01;
          m.rotation.z += Math.random() * 0.01;
        });
        // 用渲染器渲染
        renderer.render(scene, camera);

        // 重复渲染，需要查一下
        // 请求动画帧
        // requestAnimationFrame实现周期性循环执行
        // requestAnimationFrame默认每秒钟执行60次，但不一定能做到，要看代码的性能
        requestAnimationFrame(render); // 请求再次执行函数render, 放上面下面都行
      }

      // 执行渲染方法
      render();
    </script>
  </head>
  <body>
    测试1
    <div id="monitor"></div>
  </body>
</html>
